#!/bin/bash

# 定义采集函数
collect_llc_load_misses() {
    local pids_str="$1"
    local period="$2"  # 采集周期（秒）
    local output_file="${3:-llc_load_misses.csv}"  # 输出文件，默认为llc_load_misses.csv
    
    # 参数检查
    if [[ -z "$pids_str" || -z "$period" ]]; then
        echo "Usage: collect_llc_load_misses <pid1,pid2,...> <period> [output_file]"
        echo "示例: collect_llc_load_misses '1234,5678,9012' 5 llc_data.csv"
        return 1
    fi
    
    # 解析PID列表
    IFS=',' read -ra pids <<< "$pids_str"
    
    # 检查所有PID是否存在
    for pid in "${pids[@]}"; do
        pid=$(echo "$pid" | xargs)  # 去除可能的空格
        if ! kill -0 "$pid" 2>/dev/null; then
            echo "错误: 进程 $pid 不存在"
            return 1
        fi
        echo "验证进程 $pid 存在"
    done
    
    # 检查perf命令是否可用
    if ! command -v perf &> /dev/null; then
        echo "错误: perf命令未找到，请安装perf工具"
        return 1
    fi
    
    echo "开始采集PID列表 [${pids_str}] 的LLC-load-misses，周期: $period 秒，输出到: $output_file"
    echo "按 Ctrl+C 停止采集"
    
    # 写入CSV头部
    header="timestamp"
    for pid in "${pids[@]}"; do
        pid=$(echo "$pid" | xargs)  # 去除可能的空格
        header="$header,pid_$pid"
    done
    echo "$header" > "$output_file"
    
    # 循环采集
    while true; do
        # 存储所有PID的采集结果
        declare -A results
        
        # 对每个PID进行采集
        for pid in "${pids[@]}"; do
            pid=$(echo "$pid" | xargs)  # 去除可能的空格
            
            # 执行perf命令并捕获输出
            perf_output=$(perf stat -t "$pid" -e LLC-load-misses -- sleep "$period" 2>&1)
            
            # 提取LLC-load-misses值
            llc_value=$(echo "$perf_output" | grep -o '[0-9,]*[[:space:]]*LLC-load-misses' | head -n1 | awk '{print $1}')
            
            if [[ -n "$llc_value" ]]; then
                # 移除逗号并转换为纯数字
                clean_value=$(echo "$llc_value" | tr -d ',')
                results["$pid"]=$clean_value
                
                # 输出到控制台
                timestamp=$(date '+%Y-%m-%d %H:%M:%S')
                echo "[$timestamp] PID $pid LLC-load-misses: $clean_value"
            else
                echo "警告: PID $pid 无法解析perf输出"
                results["$pid"]=0  # 无法获取值时设置为0
            fi
        done
        
        # 将所有PID的结果写入CSV文件
        csv_line=$(date '+%Y-%m-%d %H:%M:%S')
        
        # 按原始PID顺序输出值
        for pid in "${pids[@]}"; do
            pid=$(echo "$pid" | xargs)  # 去除可能的空格
            if [[ -n "${results[$pid]}" ]]; then
                csv_line="$csv_line,${results[$pid]}"
            else
                csv_line="$csv_line,0"  # 如果无法获取值，写入0
            fi
        done
        
        # 写入CSV文件
        echo "$csv_line" >> "$output_file"
        
        # 清空临时数组
        unset results
        
        # 等待下一个周期
        #sleep "$period"
    done
}

# 改进版本：支持更多perf事件
collect_llc_with_events() {
    local pids_str="$1"
    local period="$2"  # 采集周期（秒）
    local output_file="${3:-llc_load_misses.csv}"  # 输出文件
    local events="${4:-LLC-load-misses}"  # 要监控的事件列表，逗号分隔
    
    # 参数检查
    if [[ -z "$pids_str" || -z "$period" ]]; then
        echo "Usage: collect_llc_with_events <pid1,pid2,...> <period> [output_file] [events]"
        echo "示例: collect_llc_with_events '1234,5678' 5 llc_data.csv 'LLC-load-misses,LLC-loads'"
        return 1
    fi
    
    # 解析PID和事件列表
    IFS=',' read -ra pids <<< "$pids_str"
    IFS=',' read -ra event_list <<< "$events"
    
    # 检查所有PID是否存在
    for pid in "${pids[@]}"; do
        pid=$(echo "$pid" | xargs)  # 去除可能的空格
        if ! kill -0 "$pid" 2>/dev/null; then
            echo "错误: 进程 $pid 不存在"
            return 1
        fi
    done
    
    # 检查perf命令是否可用
    if ! command -v perf &> /dev/null; then
        echo "错误: perf命令未找到，请安装perf工具"
        return 1
    fi
    
    echo "开始采集PID列表 [${pids_str}] 的事件 [${events}]，周期: $period 秒，输出到: $output_file"
    echo "按 Ctrl+C 停止采集"
    
    # 写入CSV头部
    header="timestamp"
    for pid in "${pids[@]}"; do
        pid=$(echo "$pid" | xargs)  # 去除可能的空格
        for event in "${event_list[@]}"; do
            event=$(echo "$event" | xargs)  # 去除可能的空格
            header="$header,pid_${pid}_${event}"
        done
    done
    echo "$header" > "$output_file"
    
    # 循环采集
    while true; do
        csv_line=$(date '+%Y-%m-%d %H:%M:%S')
        
        # 对每个PID和每个事件进行采集
        for pid in "${pids[@]}"; do
            pid=$(echo "$pid" | xargs)  # 去除可能的空格
            
            for event in "${event_list[@]}"; do
                event=$(echo "$event" | xargs)  # 去除可能的空格
                
                # 执行perf命令并捕获输出
                perf_output=$(perf stat -t "$pid" -e "$event" -- sleep "$period" 2>&1)
                
                # 提取事件值
                event_value=$(echo "$perf_output" | grep -o '[0-9,]*[[:space:]]*'$(echo "$event" | sed 's/[[\.*^$()+?{|]/\\&/g') | head -n1 | awk '{print $1}')
                
                if [[ -n "$event_value" ]]; then
                    # 移除逗号并转换为纯数字
                    clean_value=$(echo "$event_value" | tr -d ',')
                    csv_line="$csv_line,$clean_value"
                    
                    # 输出到控制台
                    timestamp=$(date '+%Y-%m-%d %H:%M:%S')
                    echo "[$timestamp] PID $pid $event: $clean_value"
                else
                    echo "警告: PID $pid 无法解析 $event 输出"
                    csv_line="$csv_line,0"  # 无法获取值时设置为0
                fi
            done
        done
        
        # 写入CSV文件
        echo "$csv_line" >> "$output_file"
        
        # 等待下一个周期
        #sleep "$period"
    done
}

# 新增函数：采集LLC-load-misses、l1i_cache_refill和l2i_cache_refill三项统计
collect_enhanced_stats() {
    local pids_str="$1"
    local period="$2"  # 采集周期（秒）
    local output_file="${3:-enhanced_stats.csv}"  # 输出文件，默认为enhanced_stats.csv
    local events="LLC-load-misses,l1i_cache_refill,l2i_cache_refill"  # 固定的三个事件
    
    # 参数检查
    if [[ -z "$pids_str" || -z "$period" ]]; then
        echo "Usage: collect_enhanced_stats <pid1,pid2,...> <period> [output_file]"
        echo "示例: collect_enhanced_stats '1234,5678,9012' 5 enhanced_data.csv"
        return 1
    fi
    
    # 解析PID列表
    IFS=',' read -ra pids <<< "$pids_str"
    
    # 检查所有PID是否存在
    for pid in "${pids[@]}"; do
        pid=$(echo "$pid" | xargs)  # 去除可能的空格
        if ! kill -0 "$pid" 2>/dev/null; then
            echo "错误: 进程 $pid 不存在"
            return 1
        fi
    done
    
    # 检查perf命令是否可用
    if ! command -v perf &> /dev/null; then
        echo "错误: perf命令未找到，请安装perf工具"
        return 1
    fi
    
    echo "开始采集PID列表 [${pids_str}] 的LLC-load-misses、l1i_cache_refill和l2i_cache_refill，周期: $period 秒，输出到: $output_file"
    echo "按 Ctrl+C 停止采集"
    
    # 写入CSV头部
    header="timestamp"
    for pid in "${pids[@]}"; do
        pid=$(echo "$pid" | xargs)  # 去除可能的空格
        header="$header,pid_${pid}_LLC_load_misses,pid_${pid}_l1i_cache_refill,pid_${pid}_l2i_cache_refill"
    done
    echo "$header" > "$output_file"
    
    # 循环采集
    while true; do
        csv_line=$(date '+%Y-%m-%d %H:%M:%S')
        
        # 对每个PID进行采集
        for pid in "${pids[@]}"; do
            pid=$(echo "$pid" | xargs)  # 去除可能的空格
            
            # 对每个事件进行采集
            for event in LLC-load-misses l1i_cache_refill l2i_cache_refill; do
                # 执行perf命令并捕获输出
                perf_output=$(perf stat -t "$pid" -e "$event" -- sleep "$period" 2>&1)
                
                # 提取事件值
                event_value=$(echo "$perf_output" | grep -o '[0-9,]*[[:space:]]*'$(echo "$event" | sed 's/[[\.*^$()+?{|]/\\&/g') | head -n1 | awk '{print $1}')
                
                if [[ -n "$event_value" ]]; then
                    # 移除逗号并转换为纯数字
                    clean_value=$(echo "$event_value" | tr -d ',')
                    csv_line="$csv_line,$clean_value"
                    
                    # 输出到控制台
                    timestamp=$(date '+%Y-%m-%d %H:%M:%S')
                    echo "[$timestamp] PID $pid $event: $clean_value"
                else
                    echo "警告: PID $pid 无法解析 $event 输出"
                    csv_line="$csv_line,0"  # 无法获取值时设置为0
                fi
            done
        done
        
        # 写入CSV文件
        echo "$csv_line" >> "$output_file"
        
        # 等待下一个周期
        sleep "$period"
    done
}

# 调用新增的函数
collect_enhanced_stats "$1" "$2" "$3"




